package com.settlement.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.settlement.system.common.constant.SystemConstants;
import com.settlement.system.common.enums.OrderEnum;
import com.settlement.system.common.util.StringUtils;
import com.settlement.system.mapper.SysAuditNoLinkMapper;
import com.settlement.system.mapper.SysOrderDetailMapper;
import com.settlement.system.mapper.SysOrderMapper;
import com.settlement.system.model.entity.*;
import com.settlement.system.model.query.OrderPageQuery;
import com.settlement.system.model.vo.SysOrderVO;
import com.settlement.system.service.SnowflakeIdWorker;
import com.settlement.system.service.SysOrderService;
import com.settlement.system.service.SysPlatformService;
import com.settlement.system.service.SysStoreService;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 标准订单 服务实现类
 * </p>
 *
 * @author huangrensen
 * @since 2023-09-20
 */
@Service
@RequiredArgsConstructor
public class SysOrderServiceImpl extends ServiceImpl<SysOrderMapper, SysOrder> implements SysOrderService {

    private final static Logger logger = LoggerFactory.getLogger(SysOrderServiceImpl.class);
    private final SysStoreService storeService;

    private final SysPlatformService platformService;

    private final SysOrderDetailMapper orderDetailMapper;

    private final RedisTemplate redisTemplate;

    private final SysAuditNoLinkMapper auditNoLinkMapper;

    private final SnowflakeIdWorker snowflakeIdWorker = SnowflakeIdWorker.getInstance();

    @Override
    public Page<SysOrderVO> getOrderPage(OrderPageQuery queryParams) {
        // 查询参数
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        // 拼接月份列表
        List<String> monthList = new ArrayList<>();
        String endMonthStr = queryParams.getEndMonth().replaceAll("-", "");
        LocalDate endMonth = LocalDate.parse(endMonthStr + "01", DateTimeFormatter.ofPattern("yyyyMMdd"));
        LocalDate startTime = LocalDate.parse(queryParams.getStartMonth().replaceAll("-", "") + "01", DateTimeFormatter.ofPattern(
                "yyyyMMdd"));
        // 获取已经生成的表名
        Object object = redisTemplate.opsForValue().get(SystemConstants.ORDER_KEY);
        List<String> tableNameList;
        if (object != null) {
            tableNameList = (List<String>) object;
        } else {
            tableNameList = this.baseMapper.getAllTable();
            // 添加缓存
            redisTemplate.opsForValue().set(SystemConstants.ORDER_KEY, tableNameList, 1, TimeUnit.HOURS);
        }
        // 循环追加月份
        while (!startTime.isAfter(endMonth)) {
            monthList.add(startTime.format(DateTimeFormatter.ofPattern("yyyyMM")));
            startTime = startTime.plusMonths(1);
        }
        // 根据月份判断数据库表是否存在
        List<String> existTableList = new ArrayList<>();
        String tableName;
        for (String month : monthList) {
            tableName = "sys_order_%s".formatted(month);
            if (tableNameList.contains(tableName)) {
                existTableList.add(tableName);
            }
        }
        queryParams.setTableNameList(existTableList);
        // 查询数据
        Page<SysOrder> orderPage = new Page<>(pageNum, pageSize);
        Page<SysOrderVO> orderVOPage = new Page<>(pageNum, pageSize);
        if (existTableList.size() == 0) {
            return orderVOPage;
        }
        // 查询所有平台
        List<SysPlatform> platformList = platformService.list();
        Page<SysOrderVO> pageVo = new Page<>();
        orderPage = this.baseMapper.getPage(orderPage, queryParams);
        BeanUtil.copyProperties(orderPage, pageVo, "records");
        List<SysOrder> records = orderPage.getRecords();
        List<SysOrderVO> recordVos = new ArrayList<>();
        for (SysOrder record : records) {
            SysOrderVO vo = new SysOrderVO();
            BeanUtil.copyProperties(record, vo);
            recordVos.add(vo);
        }
        if (records.size() > 0) {
            List<SysStore> storeList = storeService.list(new LambdaQueryWrapper<SysStore>().in(SysStore::getId, records.stream().map(SysOrder::getStoreId).filter(Objects::nonNull).toList()));
            for (SysOrderVO recordVo : recordVos) {
                storeList.stream().filter(store -> store.getId().equals(recordVo.getStoreId())).findFirst().ifPresent(store -> {
                    // 电商平台店铺名称
                    recordVo.setPlatformStoreName(store.getCommercePlatformStoreName());
                    // 对账系统店铺名称
                    recordVo.setBillStoreName(store.getBillSystemStoreName());
                    // 内部系统电商平台名称
                    recordVo.setInnerShopName(store.getInnerSystemCommercePlatformName());
                    // 内部系统店铺名称
                    recordVo.setShopName(store.getInnerSystemStoreName());
                    // 财务系统店铺名称
                    recordVo.setBillSysStoreName(store.getFinanceSystemStoreName());
                });
                // 平台名称
                platformList.stream().filter(platform -> platform.getPlatformKey().equals(recordVo.getPlatform())).findFirst().ifPresent(platform -> {
                    recordVo.setPlatform(platform.getReconciliationSystemName());
                });
                // 账单月份
                recordVo.setBillMonth(queryParams.getBillMonth());
            }
        }
        pageVo.setRecords(recordVos);
        return pageVo;
    }

    @Override
    public Page<SysOrder> getAllOrderPage(OrderPageQuery queryParams) {
        // 查询参数
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        // 查询数据
        if (!StringUtils.hasText(queryParams.getTableName())) {
            String tableName = "sys_bill_%s".formatted(queryParams.getBillMonth());
            queryParams.setTableName(tableName);
        }
        if (!StringUtils.hasText(this.baseMapper.existTable(queryParams.getTableName()))) {
            return new Page<>(pageNum, pageSize);
        }
        Page<SysOrder> page = new Page<>(pageNum, pageSize);
        return this.baseMapper.getAllPage(page, queryParams);
    }

    @Override
    public SysOrder insertOrUpdate(SysOrder sysOrder, boolean isReturnOrder) {
        sysOrder.setLinkNo(StringUtils.replaceStr(sysOrder.getLinkNo(), "'", ""));
        OrderPageQuery queryParams = new OrderPageQuery();
        queryParams.setTableName(sysOrder.getTableName());
        queryParams.setLinkNo(sysOrder.getLinkNo());
        queryParams.setStoreId(sysOrder.getStoreId());
        List<SysOrder> sysOrderList;
        if (!StringUtils.hasText(this.baseMapper.existTable(queryParams.getTableName()))) {
            this.baseMapper.createTable(queryParams.getTableName());
            sysOrderList = new ArrayList<>();
            redisTemplate.delete(SystemConstants.ORDER_KEY);
        } else {
            sysOrderList = this.baseMapper.getList(queryParams);
        }
        // 通过关联单号查询所有的订单明细
        SysOrderDetail sysOrderDetail = new SysOrderDetail();
        sysOrderDetail.setTableName("sys_order_detail_%s".formatted(sysOrder.getTableName().replaceAll("sys_order_", "")));
        sysOrderDetail.setSourceMainNo(sysOrder.getLinkNo());
        List<SysOrderDetail> orderDetailList = orderDetailMapper.getList(sysOrderDetail);
        // 因为标准订单汇总是按照主单号（关联单号）进行的汇总，所以这里只取一条即可
        BigDecimal totalAmount = BigDecimal.ZERO;
        int qtyTotal = 0;
        if (sysOrderList.size() > 0 && !StringUtils.hasText(sysOrderList.get(0).getFileAuditId())) {
            SysOrder order = sysOrderList.get(0);
            // 两种情况
            // 1、标准订单明细中只有退货数据（退货数量/退货金额有值）：发退货时间=当前明细中最晚发退货时间
            // 2、上述情况除外的：发退货时间=排除退货数据后，当前明细中最晚发退货时间
            BeanUtil.copyProperties(sysOrder, order, "id", "sendReturnTime", "qty", "sendAmount", "returnQty", "returnAmount");
            if (isReturnOrder) {
                if (Objects.isNull(order.getSendReturnTime())) {
                    // 如果有退货数据，并且发货时间为空，则发退货时间=退货时间
                    order.setSendReturnTime(sysOrder.getSendReturnTime());
                } else {
                    if (order.getSendReturnTime().isBefore(sysOrder.getSendReturnTime())) {
                        order.setSendReturnTime(sysOrder.getSendReturnTime());
                    }
                }
            } else {
                // 发退货时间=当前明细中最晚发退货时间
                if (Objects.isNull(order.getSendReturnTime())) {
                    order.setSendReturnTime(sysOrder.getSendReturnTime());
                } else {
                    if (order.getSendReturnTime().isBefore(sysOrder.getSendReturnTime())) {
                        // 最晚发退货时间
                        order.setSendReturnTime(sysOrder.getSendReturnTime());
                    }
                }
            }
            // 发货数量
            order.setQty(orderDetailList.stream().mapToInt(SysOrderDetail::getQty).sum());
            // 发货金额
            order.setSendAmount(orderDetailList.stream().map(SysOrderDetail::getSendAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
            // 退货数量
            for (SysOrderDetail orderDetail : orderDetailList) {
                qtyTotal += Math.abs(orderDetail.getReturnQty());
            }
            order.setReturnQty(-qtyTotal);
            // 退货金额
            for (SysOrderDetail orderDetail : orderDetailList) {
                totalAmount = totalAmount.add(orderDetail.getReturnAmount().abs());
            }
            order.setReturnAmount(totalAmount.negate());
            order.setTableName(sysOrder.getTableName());
            this.baseMapper.update(order);
            return order;
        } else {
            orderDetailList = orderDetailList.stream().filter(od -> !StringUtils.hasText(od.getFileAuditId())).toList();
            sysOrder.setId(snowflakeIdWorker.nextId(sysOrder.getTableName().replaceAll("sys_order_", "")));
            // 发货数量
            sysOrder.setQty(orderDetailList.stream().mapToInt(SysOrderDetail::getQty).sum());
            // 发货金额
            sysOrder.setSendAmount(orderDetailList.stream().map(SysOrderDetail::getSendAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
            // 退货数量
            for (SysOrderDetail orderDetail : orderDetailList) {
                qtyTotal += Math.abs(orderDetail.getReturnQty());
            }
            sysOrder.setReturnQty(-qtyTotal);
            // 退货金额
            for (SysOrderDetail orderDetail : orderDetailList) {
                totalAmount = totalAmount.add(orderDetail.getReturnAmount().abs());
            }
            sysOrder.setReturnAmount(totalAmount.negate());
            this.baseMapper.insertData(sysOrder);
            // 保存一份核销单订单对应关系
            // 生成一个对应规则
            try {
                int year = LocalDate.now().getYear();
                String tableName = "sys_audit_no_link_%s".formatted(year);
                if (!StringUtils.hasText(auditNoLinkMapper.existTable(tableName))) {
                    auditNoLinkMapper.createTable(tableName);
                }
                SysAuditNoLink sysAuditNoLink = new SysAuditNoLink();
                sysAuditNoLink.setLinkNo(sysOrder.getLinkNo());
                sysAuditNoLink.setType(OrderEnum.ORDER.getValue());
                // 因为账单有多条，所以这里只要存账单的月份即可，到时查询根账单查关联单号
                sysAuditNoLink.setTableId(sysOrder.getId());
                sysAuditNoLink.setTableName(tableName);
                auditNoLinkMapper.insertData(sysAuditNoLink);
            } catch (Exception e) {
                logger.error("插入失败：" + e.getMessage());
            }
            return sysOrder;
        }
    }

    @Override
    public void updateAuditId(List<SysOrder> sysOrders, String auditId, String fileAuditId) {
        for (SysOrder sysOrder : sysOrders) {
            String tableName = "sys_order_detail_%s".formatted(sysOrder.getTableName().replaceAll("sys_order_", ""));
            // 归档ID
            sysOrder.setFileAuditId(fileAuditId);
            this.baseMapper.update(sysOrder);
            if (StringUtils.hasText(orderDetailMapper.existTable(tableName))) {
                SysOrderDetail query = new SysOrderDetail();
                query.setTableName(tableName);
                query.setSourceMainNo(sysOrder.getLinkNo());
                List<SysOrderDetail> orderDetailList = orderDetailMapper.getList(query);
                for (SysOrderDetail orderDetail : orderDetailList) {
                    if(StringUtils.hasText(orderDetail.getFileAuditId())){
                        continue;
                    }
                    // 更新明细的归档ID
                    orderDetailMapper.updateAuditId(tableName, auditId, fileAuditId, orderDetail.getId());
                }
            }
        }
    }

    @Override
    public Set<String> columnList() {
        return SysOrder.getColumnMap().keySet();
    }
}
